package com.jiangyao.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jiangyao.common.constants.AdminUserConstants;
import com.jiangyao.common.constants.CacheConstants;
import com.jiangyao.common.exception.ServerException;
import com.jiangyao.common.utils.MD5util;
import com.jiangyao.common.utils.StringUtils;
import com.jiangyao.component.RedisComponent;
import com.jiangyao.dao.IAdminRoleDao;
import com.jiangyao.dao.IAdminUserDao;
import com.jiangyao.dao.IAdminUserOrgClassDao;
import com.jiangyao.dao.IClassInfoDao;
import com.jiangyao.model.dto.backend.AdminUserDTO;
import com.jiangyao.model.dto.backend.AdminUserListPageDTO;
import com.jiangyao.model.dto.backend.AdminUserSearchDTO;
import com.jiangyao.model.entity.AdminRole;
import com.jiangyao.model.entity.AdminUser;
import com.jiangyao.model.entity.AdminUserOrgClass;
import com.jiangyao.model.entity.ClassInfo;
import com.jiangyao.model.entity.LoginLog;
import com.jiangyao.model.vo.AdminUserSessionVO;
import com.jiangyao.service.AdminRoleService;
import com.jiangyao.service.AdminUserOrgClassService;
import com.jiangyao.service.AdminUserService;
import com.jiangyao.service.LoginLogService;
import lombok.EqualsAndHashCode;
import org.dozer.DozerBeanMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * <p>
 * 管理员信息 服务实现类
 * </p>
 *
 * @author yangyongchuan
 * @since 2020-08-12
 */
@Service
public class AdminUserServiceImpl extends BaseServiceImpl<IAdminUserDao, AdminUser> implements AdminUserService {

	@Autowired
	private DozerBeanMapper dozerBeanMapper;

	@Autowired
	private RedisComponent redisComponent;

	@Autowired
	private IAdminRoleDao adminRoleDao;

	@Autowired
	private IAdminUserOrgClassDao adminUserOrgClassDao;

	@Autowired
	private AdminRoleService adminRoleService;

	@Autowired
	private LoginLogService loginLogService;

	@Autowired
	private IClassInfoDao classInfoDao;

	@Override
	public AdminUserSessionVO login(AdminUserDTO adminUserDTO) {
		QueryWrapper<AdminUser> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("login_name", adminUserDTO.getLoginName());
		queryWrapper.last(" LIMIT 1");
		AdminUser adminUser = this.getOne(queryWrapper);
		if (adminUser == null) {
			throw new ServerException(100, "账号或密码错误");
		}
		String password = MD5util.generateSymbol(adminUserDTO.getPassword());
		if (!adminUser.getPassword().equals(password)) {
			throw new ServerException(100, "账号或密码错误");
		}
		AdminUserSessionVO adminUserSessionVO = dozerBeanMapper.map(adminUser, AdminUserSessionVO.class);
		// 登录token
		String token = UUID.randomUUID().toString();
		adminUserSessionVO.setToken(token);
		// 获取角色ID集合
		getRoleIdList(adminUserSessionVO);
		// 获取组织与班级 集合
		adminUserSessionVO = packageOrgAndClass(adminUserSessionVO);

		// redis保存登录信息
		redisComponent.set(CacheConstants.CACHE_KEY_TOKEN_BACKEND_PREFIX + token, adminUserSessionVO, CacheConstants.CACHE_TIME_1_DAY);
		// 保存登录日志
		LoginLog loginLog = LoginLog.builder().userId(adminUserSessionVO.getAdminId()).token(token).userType(1).build();
		loginLogService.saveLoginLog(loginLog);
		return adminUserSessionVO;
	}

	/**
	 * 获取登录用户角色集合
	 *
	 * @param adminUserSessionVO 登录用户信息
	 */
	private void getRoleIdList(AdminUserSessionVO adminUserSessionVO) {
		QueryWrapper<AdminRole> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("admin_id", adminUserSessionVO.getAdminId());
		List<AdminRole> list = adminRoleDao.selectList(queryWrapper);
		if (CollectionUtils.isEmpty(list)) {
			return;
		}
		List<Integer> roleIdList = new ArrayList<>(list.size());
		list.forEach(adminRole -> roleIdList.add(adminRole.getRoleId()));
		adminUserSessionVO.setRoleIdList(roleIdList);
	}

	/**
	 * 获取封装登录用户组织 班级集合
	 *
	 * @param adminUserSessionVO 登录用户信息
	 */
	@Override
	public AdminUserSessionVO packageOrgAndClass(AdminUserSessionVO adminUserSessionVO) {
		QueryWrapper<AdminUserOrgClass> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("admin_id", adminUserSessionVO.getAdminId());
		queryWrapper.orderByDesc("create_time");
		List<AdminUserOrgClass> list = adminUserOrgClassDao.selectList(queryWrapper);
		if (CollectionUtils.isEmpty(list)) {
			adminUserSessionVO.setOrgIdList(new ArrayList<>());
			adminUserSessionVO.setClassIdList(new ArrayList<>());
			return adminUserSessionVO;
		}
		List<Integer> orgIdList = new ArrayList<>(list.size());
		List<Integer> classIdList = new ArrayList<>(list.size());
		list.forEach(adminUserOrgClass -> {
			if (adminUserOrgClass.getOrgId() != null) {
				orgIdList.add(adminUserOrgClass.getOrgId());
			}
			if (adminUserOrgClass.getClassId() != null) {
				classIdList.add(adminUserOrgClass.getClassId());
			}
		});
		adminUserSessionVO.setOrgIdList(orgIdList);

		// 通过组织id获取班级id集合
		if (!CollectionUtils.isEmpty(orgIdList)) {
			QueryWrapper<ClassInfo> classInfoQueryWrapper = new QueryWrapper<>();
			classInfoQueryWrapper.in("org_id", orgIdList);
			classInfoQueryWrapper.select("class_id");
			List<ClassInfo> classInfoList = classInfoDao.selectList(classInfoQueryWrapper);
			if (!CollectionUtils.isEmpty(classInfoList)) {
				classIdList.addAll(classInfoList.stream().map(ClassInfo::getClassId).collect(Collectors.toList()));
			}
			// 组织下没有班级，添加：-1
			if (CollectionUtils.isEmpty(classIdList)) {
				classIdList.add(-1);
			}
		}
		List<Integer> classIdList2 = classIdList.stream().distinct().collect(Collectors.toList());
		adminUserSessionVO.setClassIdList(classIdList2);
		return adminUserSessionVO;
	}

	@Override
	public Page<AdminUser> getListPage(AdminUserListPageDTO listDTO) {
		QueryWrapper<AdminUser> adminUserQW = new QueryWrapper<>();
		if (StringUtils.isNotEmpty(listDTO.getLoginName())) {
			adminUserQW.like("login_name", listDTO.getLoginName());
		}
		if (StringUtils.isNotEmpty(listDTO.getPhone())) {
			adminUserQW.like("phone", listDTO.getPhone());
		}
		if (StringUtils.isNotEmpty(listDTO.getAdminName())) {
			adminUserQW.like("admin_name", listDTO.getAdminName());
		}
		adminUserQW.orderByDesc("admin_id");
		Page<AdminUser> page = new Page<>(listDTO.getPageNo(), listDTO.getPageSize());
		this.page(page, adminUserQW);
		return page;
	}

	@Override
	public void add(AdminUserDTO adminUserDTO) {
		QueryWrapper<AdminUser> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("login_name", adminUserDTO.getLoginName());
		int count = this.count(queryWrapper);
		if (count > 0) {
			throw new ServerException(100, "账号已存在");
		}
		// 获取当前登录用户
		AdminUserSessionVO adminUserSessionVO = getAdminLoginSession();
		AdminUser adminUser = dozerBeanMapper.map(adminUserDTO, AdminUser.class);
		adminUser.setAdminId(null);
		adminUser.setStatus(1);
		// 不设置密码，就默认为：123456
		if (StringUtils.isEmpty(adminUser.getPassword())) {
			adminUser.setPassword("123456");
		}
		adminUser.setPassword(MD5util.generateSymbol(adminUser.getPassword().trim()));

		adminUser.setCreateAdminId(adminUserSessionVO.getAdminId());
		adminUser.setCreateTime(new Date());

		// 保存账号
		this.save(adminUser);

		// 保存用户与角色
		saveAdminRole(adminUser.getAdminId(), adminUserDTO.getRoleIdList());
	}

	/**
	 * 保存用户与角色
	 *
	 * @param adminId    账号ID
	 * @param roleIdList 角色ID集合
	 */
	@Override
	public void saveAdminRole(Integer adminId, List<Integer> roleIdList) {
		if (adminId == null) {
			return;
		}
		// 先删除以前角色
		QueryWrapper<AdminRole> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("admin_id", adminId);
		adminRoleService.remove(queryWrapper);

		if (CollectionUtils.isEmpty(roleIdList)) {
			return;
		}
		List<AdminRole> adminRoleList = new ArrayList<>(roleIdList.size());
		roleIdList.forEach(roleId -> {
			if (roleId > 0) {
				AdminRole adminRole = new AdminRole();
				adminRole.setAdminId(adminId);
				adminRole.setRoleId(roleId);
				adminRoleList.add(adminRole);
			}
		});
		adminRoleService.saveBatch(adminRoleList);
	}


	@Override
	public void edit(AdminUserDTO adminUserDTO) {
		AdminUser adminUserDB = this.getById(adminUserDTO.getAdminId());
		if (adminUserDB == null) {
			throw new ServerException(100, "账号不存在");
		}

		// 获取当前登录用户id
		Integer loginAdminUserId = getLoginAdminUserId();
		// 编辑管理账号信息
		updateAdminUser(loginAdminUserId, adminUserDTO);

		// 保存用户与角色
		saveAdminRole(adminUserDTO.getAdminId(), adminUserDTO.getRoleIdList());
	}

	@Override
	public void editMyself(AdminUserDTO adminUserDTO) {
		// 获取当前登录用户id
		Integer loginAdminUserId = getLoginAdminUserId();
		if (!getLoginAdminUserId().equals(adminUserDTO.getAdminId())) {
			throw new ServerException(100, "只能修改自己的账号");
		}
		// 编辑管理账号信息
		updateAdminUser(loginAdminUserId, adminUserDTO);
	}

	/**
	 * 编辑管理账号信息
	 *
	 * @param updateAdminId 修改账号的用户ID
	 * @param adminUserDTO  账号信息
	 */
	private void updateAdminUser(Integer updateAdminId, AdminUserDTO adminUserDTO) {
		AdminUser adminUser = dozerBeanMapper.map(adminUserDTO, AdminUser.class);
		UpdateWrapper<AdminUser> updateWrapper = new UpdateWrapper<>();
		updateWrapper.eq("admin_id", adminUserDTO.getAdminId());
		updateWrapper.set("phone", adminUserDTO.getPhone()).set("admin_name", adminUserDTO.getAdminName())
				.set("admin_photo", adminUserDTO.getAdminPhoto()).set("admin_desc", adminUserDTO.getAdminDesc())
				.set("status", adminUserDTO.getStatus());
		if (StringUtils.isNotEmpty(adminUserDTO.getPassword())) {
			updateWrapper.set("password", MD5util.generateSymbol(adminUser.getPassword().trim()));
		}
		updateWrapper.set("update_time", new Date()).set("update_admin_id", updateAdminId);

		this.update(updateWrapper);
	}


	@Override
	public void editPassword(AdminUserDTO adminUserDTO) {
		AdminUser adminUserDB = this.getById(adminUserDTO.getAdminId());
		if (adminUserDB == null) {
			throw new ServerException(100, "账号不存在");
		}
		UpdateWrapper<AdminUser> updateWrapper = new UpdateWrapper<>();
		updateWrapper.eq("admin_id", adminUserDTO.getAdminId());
		String password = adminUserDTO.getPassword();
		if (StringUtils.isEmpty(password)) {
			password = AdminUserConstants.DEFAULT_PASSWORD;
		}
		updateWrapper.set("password", MD5util.generateSymbol(password.trim()));
		updateWrapper.set("update_time", new Date()).set("update_admin_id", getLoginAdminUserId());
		this.update(updateWrapper);
	}

	@Override
	public AdminUser getByLoginName(String loginName) {
		QueryWrapper<AdminUser> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("login_name", loginName);
		queryWrapper.last(" LIMIT 1");
		return this.getOne(queryWrapper);
	}

	@Override
	public List<AdminUser> searchForSelect(AdminUserSearchDTO adminUserSearchDTO) {
		QueryWrapper<AdminUser> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("status", 1);
		// 排除超级管理员
		queryWrapper.ne("admin_id",1);

		// 组织ID不为空，查询该组织的管理员账号
		if (adminUserSearchDTO.getOrgId() != null && adminUserSearchDTO.getOrgId() > 0) {
			QueryWrapper<AdminUserOrgClass> auocQW = new QueryWrapper<>();
			auocQW.eq("org_id", adminUserSearchDTO.getOrgId());
			List<AdminUserOrgClass> list = adminUserOrgClassDao.selectList(auocQW);
			if (CollectionUtils.isEmpty(list)) {
				return null;
			}
			List<Integer> adminUserIdList = list.stream().map(AdminUserOrgClass::getAdminId).collect(Collectors.toList());
			queryWrapper.in("admin_id", adminUserIdList);
		}

		if (StringUtils.isNotBlank(adminUserSearchDTO.getAdminName())) {
			queryWrapper.like("admin_name", adminUserSearchDTO.getAdminName());
		}
		// TODO 班级选择管理员 限制逻辑不清楚
		Integer searchType = adminUserSearchDTO.getSearchType();
		if (searchType != null) {

		}
		queryWrapper.orderByDesc("admin_id");
		queryWrapper.last(" LIMIT 50");
		return this.list(queryWrapper);
	}
}
